home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
oper_sys
/
presto
/
prest1_0.lha
/
Tests
/
sos
/
sos.C
< prev
Wrap
C/C++ Source or Header
|
1991-12-11
|
3KB
|
164 lines
//
// This is a C++/Presto program to solve the sum-of-subsets problem
// using a parallel version of the backtracking algorithm described
// in Horowitz and Sahni. There is clearly something wrong with the
// policy for starting new threads since the speedup is not even
// close to linear. The speedup should be close to linear since
// this is an easily decomposable compute-intensive problem.
//
// Jeff Chase 8/15/88
// University of Washington
//
#include "presto.h"
#include "set.h"
#define DEFAULT_WORKERS 4
#define MAXWORKERS 128
int wantedsum;
Oqueue solutions;
Spinlock sol_lock;
int show_solutions = 0;
Spinlock threadlock;
int threadcount = 1;
int wantedthreads = DEFAULT_WORKERS;
Thread *workers[MAXWORKERS];
int
maxtotal(int setsize)
{
int i, sum;
sum = 0;
for(i = 0; i < setsize; i++)
sum += i;
return(sum);
}
void
sum_of_sub(Set *s, int k, int r)
{
Set *newset;
int fork, i;;
//
// Generate left child -- include k in the set and see if
// if it sums to wantedsum. If yes, add to solution list.
// If we haven't started all our threads yet, fire off a
// new thread to do the rest of this subtree for us.
//
newset = s->clone();
newset->include(k);
if (newset->sum() == wantedsum) {
sol_lock.lock();
solutions.append(newset);
sol_lock.unlock();
} else {
if (newset->sum() + k + 1 <= wantedsum) {
fork = 0;
if (threadcount < wantedthreads) {
threadlock.lock();
if (threadcount < wantedthreads) {
i = threadcount++;
fork = 1;
}
threadlock.unlock();
}
if (fork) {
workers[i] = new Thread();
workers[i]->willjoin();
workers[i]->start(0, (PFany) sum_of_sub, newset, k+1, r-k);
} else {
sum_of_sub(newset, k+1, r-k);
}
}
}
//
// Generate right child.
//
if ((s->sum() + r - k >= wantedsum)
&& (s->sum() + k + 1 <= wantedsum)) {
sum_of_sub(s, k + 1, r - k);
}
}
int
Main::init()
{
numprocessors = DEFAULT_WORKERS;
quantum = 0;
wantedsum = 23;
for (argc--, argv++; *argv && **argv == '-'; argv++, argc--)
switch (*(*argv + 1)) {
#ifdef i386
case 'a':
affinity = 1;
break;
#endif i386
case 'q':
quantum = atoi(*argv + 2);
break;
case 'n':
numprocessors = atoi(*argv + 2);
break;
case 's':
wantedsum = atoi(*argv + 2);
break;
case 't':
wantedthreads = atoi(*argv + 2);
break;
case 'v':
show_solutions = 1;
break;
default:
cerr << chr(*(*argv + 1)) << " unknown flag.\n";
return -1;
}
if (wantedthreads > MAXWORKERS) {
cerr << "Too many threads.\n";
return 1;
} else
return 0;
}
Main::main()
{
Set *empty = new Set;
Set *s;
int sc;
Timer stopwatch;
double runtime;
int i;
stopwatch.init();
stopwatch.timerstart();
sum_of_sub(empty, 0, maxtotal(128));
while(threadcount < wantedthreads);
for (i = 1; i < wantedthreads; i++) {
workers[i]->join();
}
runtime = stopwatch.timermark();
sc = 0;
while((s = (Set *)solutions.get()) != NULL) {
sc++;
if (show_solutions)
s->print(cout);
}
cout << form("Elapsed time = %g seconds.\n", runtime);
cout << form("There are %d solutions for %d.\n", sc, wantedsum);
cout.flush();
}